﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;

namespace BuildIncrement {
    public partial class SettingsForm : Form {
        private List<SolutionItem> solutionItems;

        /// <summary>
        /// Initializes a new instance of the <see cref="SettingsForm"/> class.
        /// </summary>
        public SettingsForm() {
            InitializeComponent();
        }

        /// <summary>
        /// Handles the Click event of the btnOK control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnOK_Click(object sender, EventArgs e) {
            var tnParent = tvItems.Nodes[0];

            SaveNodeProjects(tnParent);

            this.Close();
        }

        /// <summary>
        /// Saves the node projects.
        /// </summary>
        /// <param name="tnParent">The tn parent.</param>
        private void SaveNodeProjects(TreeNode tnParent) {
            // Set build options for a node...
            foreach (TreeNode childNode in tnParent.Nodes) {
                // If has sub nodes, this is not a project...
                if (childNode.Nodes.Count > 0) {
                    foreach (TreeNode subChildNodes in childNode.Nodes)
                        SaveNodeProjects(subChildNodes);
                }
                else {
                    // if not, this is a project and so definetly has 
                    // ProjectSettings in the tag...
                    var ps = childNode.Tag as ProjectSettings;

                    // if ProjectSettings is not null...
                    if (ps != null) {
                        // ...retrieve the project...
                        var project = ps.Project;

                        if (project != null) {
                            // ...and save the settings
                            Utility.SetGlobalVariable(project, "Enabled", ps.Enable ? "1" : "0");
                            Utility.SetGlobalVariable(project, "Reset", ps.Reset ? "1" : "0");
                            Utility.SetProjectDate(project, ps.StartDate);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the btnCancel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnCancel_Click(object sender, EventArgs e) {
            // Close the form
            this.Close();
        }

        /// <summary>
        /// Handles the Load event of the SettingsForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void SettingsForm_Load(object sender, EventArgs e) {
            solutionItems = new List<SolutionItem>();
            InitializeValues();
        }

        /// <summary>
        /// Initializes the values.
        /// </summary>
        private void InitializeValues() {
            // This gets all solution projects/folders in a easy to use List.
            Utility.GetSolutionItems(ref solutionItems);

            // Root is solution...
            string solutionName = Path.GetFileNameWithoutExtension(Connect.applicationObject.Solution.FileName);
            var tnParent = tvItems.Nodes.Add(solutionName);

            // Now iterate through all solution items and add accordingly...
            FillNodeWithSolutionItem(tnParent, solutionItems);

            // Select the first item by default
            if (tnParent.Nodes.Count > 0)
                tvItems.SelectedNode = tnParent.Nodes[0];

            // Select the tree control
            tvItems.Select();
        }

        /// <summary>
        /// Fills the node with solution item.
        /// </summary>
        /// <param name="tnParent">The tn parent.</param>
        /// <param name="solutionItems">The solution items.</param>
        private static void FillNodeWithSolutionItem(TreeNode tnParent, List<SolutionItem> solutionItems) {
            foreach (SolutionItem si in solutionItems) {
                if (si.ItemType == SolutionItemType.Project) {
                    var project = si.Project;

                    var ps = new ProjectSettings();
                    // Enabled for this project?
                    ps.Enable = Utility.GetGlobalVariable(project, "Enabled", "1") == "1";
                    // Reset AssemblyInfo file date?
                    ps.Reset = Utility.GetGlobalVariable(project, "Reset", "1") == "1";
                    // Start date?
                    ps.StartDate = Utility.GetProjectDate(project);
                    // Path?
                    ps.Path = project.FileName;

                    // Set the project. This makes it easy for us to save the settings
                    // at the end of the day...
                    ps.Project = project;

                    // Attach the property to the tag
                    var tn = tnParent.Nodes.Add(project.Name);
                    tn.Tag = ps;
                }
                else {
                    var folderNode = tnParent.Nodes.Add(si.Name);

                    FillNodeWithSolutionItem(folderNode, si.SubItems);
                }
            }

            // Expand the parent
            tnParent.Expand();
        }

        /// <summary>
        /// Handles the AfterSelect event of the tvItems control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.TreeViewEventArgs"/> instance containing the event data.</param>
        private void tvItems_AfterSelect(object sender, TreeViewEventArgs e) {
            // Load the currently selected node's property in the grid
            var ps = e.Node.Tag as ProjectSettings;

            // If tag is null, it means the node points to solution...
            if (ps == null) // If yes, disable the property grid
                pgSettings.Enabled = false;
            else {
                pgSettings.Enabled = true;
                pgSettings.SelectedObject = ps;
            }
        }

        /// <summary>
        /// Sets the build for node.
        /// </summary>
        /// <param name="tnParent">The tn parent.</param>
        /// <param name="enabled">if set to <c>true</c> [enabled].</param>
        private void SetBuildForNode(TreeNode tnParent, bool enabled) {
            // Set build options for a node...
            foreach (TreeNode childNode in tnParent.Nodes) {
                // If has sub nodes, this is not a project...
                if (childNode.Nodes.Count > 0) {
                    foreach (TreeNode subChildNodes in childNode.Nodes)
                        SetBuildForNode(subChildNodes, enabled);
                }
                else {
                    // if not, this is a project and so definetly has 
                    // ProjectSettings in the tag...
                    var ps = childNode.Tag as ProjectSettings;

                    if (ps != null)
                        ps.Enable = enabled;
                }
            }
        }

        /// <summary>
        /// Sets the build for all nodes.
        /// </summary>
        /// <param name="enabled">if set to <c>true</c> [enabled].</param>
        private void SetBuildForAllNodes(bool enabled) {
            // Set build property grid's value to a specific value for
            // all project nodes...
            var tnParent = tvItems.SelectedNode;

            if (tnParent != null) {
                SetBuildForNode(tnParent, enabled);

                pgSettings.Refresh();
            }
        }

        /// <summary>
        /// Handles the Click event of the enableBuildForAllChildrenToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void enableBuildForAllChildrenToolStripMenuItem_Click(object sender, EventArgs e) {
            // Set build property grid's value to a true for
            // all project nodes...
            SetBuildForAllNodes(true);
        }

        /// <summary>
        /// Handles the Click event of the disableBuildForAllChildrenToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void disableBuildForAllChildrenToolStripMenuItem_Click(object sender, EventArgs e) {
            // Set build property grid's value to a false for
            // all project nodes...
            SetBuildForAllNodes(false);
        }

        /// <summary>
        /// Handles the MouseUp event of the tvItems control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void tvItems_MouseUp(object sender, MouseEventArgs e) {
            // Show menu only if the right mouse button is clicked.
            if (e.Button == MouseButtons.Right) {
                // Point where the mouse is clicked.
                Point p = new Point(e.X, e.Y);

                // Get the node that the user has clicked.
                var node = tvItems.GetNodeAt(p);
                if (node != null) {
                    // Select the node the user has clicked.
                    tvItems.SelectedNode = node;

                    // Display ContextMenu only if a non-project node is selected
                    if (node.Tag == null)
                        mnuTreeNodes.Show(tvItems, p);
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the btnRefresh control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnRefresh_Click(object sender, EventArgs e) {
            InitializeValues();
        }
    }
}
